package com.pai4j.user.service.group;

import com.pai4j.common.enums.*;
import com.pai4j.common.exception.BusinessException;
import com.pai4j.common.util.JsonUtil;
import com.pai4j.domain.vo.request.group.HandleInvitationRequestVO;
import com.pai4j.domain.vo.request.group.InviteToGroupRequestVO;
import com.pai4j.domain.vo.request.group.JoinGroupRequestVO;
import com.pai4j.domain.vo.response.group.GroupInvitationResponseVO;
import com.pai4j.domain.vo.response.group.JoinGroupResponseVO;
import com.pai4j.domain.vo.response.UserBaseResponseInfoVO;
import com.pai4j.user.repository.dao.*;
import com.pai4j.user.repository.entity.*;
import com.pai4j.user.service.UserService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 群聊邀请服务
 */
@Slf4j
@Service
public class GroupInvitationService {

    @Resource
    private IGroupInvitationDAO groupInvitationDAO;
    
    @Resource
    private IGroupInfoDAO groupInfoDAO;
    
    @Resource
    private IGroupMemberDAO groupMemberDAO;
    
    @Resource
    private IGroupOperationLogDAO groupOperationLogDAO;
    
    @Autowired
    private UserService userService;
    
    @Autowired
    private GroupMemberService groupMemberService;
    
    @Autowired
    private com.pai4j.user.service.approval.PendingApprovalService pendingApprovalService;

    /**
     * 邀请用户加入群聊（强一致性）
     * 同时同步到统一待审核表
     */
    @Transactional
    public List<String> inviteToGroup(InviteToGroupRequestVO request) {
        // 1. 验证群聊是否存在
        GroupInfoEntity groupInfo = groupInfoDAO.findByPaiId(request.getGroupPaiId());
        if (groupInfo == null) {
            throw new BusinessException("群聊不存在");
        }
        
        // 2. 验证邀请人权限
        if (!groupMemberService.hasPermission(request.getGroupPaiId(), request.getInviterAccount(), "member")) {
            throw new BusinessException("邀请人不在群内");
        }
        
        // 3. 检查群成员数量限制
        Long currentMemberCount = groupMemberDAO.countActiveMembers(request.getGroupPaiId());
        if (currentMemberCount + request.getInviteeAccounts().size() > groupInfo.getMaxMembers()) {
            throw new BusinessException("邀请人数超过群成员上限");
        }
        
        Date now = new Date();
        Date expireTime = request.getExpireTime();
        if (expireTime == null) {
            // 默认7天过期
            Calendar calendar = Calendar.getInstance();
            calendar.add(Calendar.DAY_OF_MONTH, 7);
            expireTime = calendar.getTime();
        }
        
        List<String> successInvitations = new ArrayList<>();
        
        // 4. 批量创建邀请记录
        for (String inviteeAccount : request.getInviteeAccounts()) {
            try {
                // 检查用户是否已在群内
                if (groupMemberDAO.existsByGroupPaiIdAndUserAccount(request.getGroupPaiId(), inviteeAccount)) {
                    log.warn("用户 {} 已在群 {} 内，跳过邀请", inviteeAccount, request.getGroupPaiId());
                    continue;
                }
                
                // 检查是否已有待处理的邀请
                GroupInvitationEntity existingInvitation = groupInvitationDAO.findByGroupPaiIdAndInviterAccountAndInviteeAccount(
                        request.getGroupPaiId(), request.getInviterAccount(), inviteeAccount);
                if (existingInvitation != null && GroupInvitationStatusEnum.isPending(existingInvitation.getInvitationStatus())) {
                    log.warn("用户 {} 已有待处理的群 {} 邀请，跳过", inviteeAccount, request.getGroupPaiId());
                    continue;
                }
                
                // 创建邀请记录
                GroupInvitationEntity invitation = new GroupInvitationEntity();
                invitation.setGroupPaiId(request.getGroupPaiId());
                invitation.setInviterAccount(request.getInviterAccount());
                invitation.setInviteeAccount(inviteeAccount);
                invitation.setInvitationCode(generateInvitationCode());
                invitation.setInvitationMessage(request.getInvitationMessage());
                invitation.setInvitationStatus(GroupInvitationStatusEnum.PENDING.getStatus());
                invitation.setExpireTime(expireTime);
                invitation.setCreateDate(now);
                invitation.setUpdateDate(now);
                
                GroupInvitationEntity savedInvitation = groupInvitationDAO.save(invitation);
                
                // 同步创建统一待审核记录（强一致性）
                // 注意：群邀请的审批人是被邀请人（inviteeAccount），申请人是邀请人（inviterAccount）
                pendingApprovalService.createPendingApproval(
                        PendingApprovalTypeEnum.GROUP_INVITATION.getType(),  // 类型=3（群邀请）
                        savedInvitation.getId(),                              // 业务记录ID
                        request.getInviterAccount(),                          // 申请人=邀请人
                        inviteeAccount,                                       // 审批人=被邀请人
                        request.getGroupPaiId(),                              // 目标ID=群ID
                        request.getInvitationMessage(),                       // 申请留言
                        GroupInvitationStatusEnum.PENDING.getStatus(),       // 状态=待处理
                        expireTime                                            // 过期时间
                );
                
                successInvitations.add(inviteeAccount);
                
                log.info("成功创建群聊邀请：群 {} 邀请人 {} 被邀请人 {}，已同步到统一待审核表", 
                        request.getGroupPaiId(), request.getInviterAccount(), inviteeAccount);
                
            } catch (Exception e) {
                log.error("创建群聊邀请失败：群 {} 邀请人 {} 被邀请人 {}", 
                         request.getGroupPaiId(), request.getInviterAccount(), inviteeAccount, e);
            }
        }
        
        return successInvitations;
    }

    /**
     * 处理群聊邀请（接受/拒绝）（强一致性）
     * 同时同步更新统一待审核表
     */
    @Transactional
    public boolean handleInvitation(HandleInvitationRequestVO request) {
        // 1. 查找邀请记录
        GroupInvitationEntity invitation = null;
        if (request.getInvitationId() != null) {
            invitation = groupInvitationDAO.findById(request.getInvitationId()).orElse(null);
        } else if (StringUtils.isNotBlank(request.getInvitationCode())) {
            invitation = groupInvitationDAO.findByInvitationCode(request.getInvitationCode());
        }
        
        if (invitation == null) {
            throw new BusinessException("邀请记录不存在");
        }
        
        // 2. 验证邀请状态
        if (!GroupInvitationStatusEnum.isPending(invitation.getInvitationStatus())) {
            throw new BusinessException("邀请已处理");
        }
        
        // 3. 验证邀请是否过期
        if (invitation.getExpireTime() != null && invitation.getExpireTime().before(new Date())) {
            throw new BusinessException("邀请已过期");
        }
        
        // 4. 验证被邀请人
        if (!invitation.getInviteeAccount().equals(request.getInviteeAccount())) {
            throw new BusinessException("无权处理此邀请");
        }
        
        Date now = new Date();
        
        // 5. 更新邀请状态
        invitation.setInvitationStatus(request.getHandleResult());
        invitation.setResponseTime(now);
        invitation.setUpdateDate(now);
        groupInvitationDAO.save(invitation);
        
        // 5.1 同步更新统一待审核表（强一致性）
        pendingApprovalService.updateApprovalStatus(
                PendingApprovalTypeEnum.GROUP_INVITATION.getType(),  // 类型=3（群邀请）
                invitation.getId(),                                   // 业务记录ID
                request.getHandleResult(),                            // 新的审批状态
                request.getInviteeAccount(),                          // 处理人=被邀请人
                null                                                  // 审批意见（邀请场景无需意见）
        );
        log.info("群聊邀请状态已同步到统一待审核表：invitationId={}, status={}", 
                invitation.getId(), request.getHandleResult());
        
        // 6. 如果接受邀请，则调用GroupMemberService.joinGroup加入群聊
        // 注意：joinGroup会同时处理群成员表、账号关系表和缓存同步
        if (GroupInvitationStatusEnum.isAccepted(request.getHandleResult())) {
            JoinGroupRequestVO joinRequest = new JoinGroupRequestVO();
            joinRequest.setGroupPaiId(invitation.getGroupPaiId());
            joinRequest.setUserAccount(invitation.getInviteeAccount());
            joinRequest.setJoinType(GroupJoinTypeEnum.INVITED.getType());
            joinRequest.setInviterAccount(invitation.getInviterAccount());
            
            try {
                // 调用统一的加群方法，确保数据一致性
                JoinGroupResponseVO joinResult = groupMemberService.joinGroup(joinRequest);
                if (joinResult.getStatus() == 1) {
                    log.info("用户 {} 通过邀请成功加入群聊 {}，所有数据和缓存已同步", invitation.getInviteeAccount(), invitation.getGroupPaiId());
                } else {
                    log.warn("用户 {} 通过邀请加入群聊 {} 未成功，状态：{}，消息：{}", 
                            invitation.getInviteeAccount(), invitation.getGroupPaiId(), joinResult.getStatus(), joinResult.getMessage());
                    throw new BusinessException(joinResult.getMessage());
                }
            } catch (BusinessException e) {
                throw e;
            } catch (Exception e) {
                log.error("用户 {} 通过邀请加入群聊 {} 失败", invitation.getInviteeAccount(), invitation.getGroupPaiId(), e);
                throw new BusinessException("加入群聊失败：" + e.getMessage());
            }
        }
        
        log.info("用户 {} 处理群聊邀请：{} 结果：{}", 
                request.getInviteeAccount(), invitation.getGroupPaiId(), 
                GroupInvitationStatusEnum.getByStatus(request.getHandleResult()).getStatusName());
        
        return true;
    }

    /**
     * 获取用户的待处理邀请列表
     */
    public List<GroupInvitationResponseVO> getPendingInvitations(String userAccount) {
        Date now = new Date();
        List<GroupInvitationEntity> invitations = groupInvitationDAO.findPendingInvitations(userAccount, now);
        
        if (invitations.isEmpty()) {
            return new ArrayList<>();
        }
        
        return convertToResponseVOs(invitations);
    }

    /**
     * 获取群聊的邀请记录（分页）
     */
    public Page<GroupInvitationResponseVO> getGroupInvitations(String groupPaiId, int page, int size) {
        Pageable pageable = PageRequest.of(page, size);
        Page<GroupInvitationEntity> invitationPage = groupInvitationDAO.findByGroupPaiIdOrderByCreateDateDesc(groupPaiId, pageable);
        
        return invitationPage.map(this::convertToResponseVO);
    }

    /**
     * 批量更新过期邀请
     */
    @Transactional
    public int updateExpiredInvitations() {
        Date now = new Date();
        return groupInvitationDAO.batchUpdateExpiredInvitations(now, now);
    }

    /**
     * 生成邀请码
     */
    private String generateInvitationCode() {
        return "INV" + System.currentTimeMillis() + String.format("%04d", new Random().nextInt(10000));
    }

    /**
     * 转换为响应VO列表
     */
    private List<GroupInvitationResponseVO> convertToResponseVOs(List<GroupInvitationEntity> invitations) {
        if (invitations.isEmpty()) {
            return new ArrayList<>();
        }
        
        // 批量获取群信息
        List<String> groupPaiIds = invitations.stream()
                .map(GroupInvitationEntity::getGroupPaiId)
                .distinct()
                .collect(Collectors.toList());
        Map<String, GroupInfoEntity> groupInfoMap = new HashMap<>();
        for (String groupPaiId : groupPaiIds) {
            GroupInfoEntity groupInfo = groupInfoDAO.findByPaiId(groupPaiId);
            if (groupInfo != null) {
                groupInfoMap.put(groupPaiId, groupInfo);
            }
        }
        
        // 批量获取邀请人信息
        List<String> inviterAccounts = invitations.stream()
                .map(GroupInvitationEntity::getInviterAccount)
                .distinct()
                .collect(Collectors.toList());
        List<UserBaseResponseInfoVO> inviterInfos = userService.batchGetUserListInfoFromCache(inviterAccounts);
        Map<String, UserBaseResponseInfoVO> inviterInfoMap = inviterInfos.stream()
                .collect(Collectors.toMap(UserBaseResponseInfoVO::getUserId, u -> u));
        
        return invitations.stream().map(invitation -> {
            GroupInfoEntity groupInfo = groupInfoMap.get(invitation.getGroupPaiId());
            UserBaseResponseInfoVO inviterInfo = inviterInfoMap.get(invitation.getInviterAccount());
            
            return GroupInvitationResponseVO.builder()
                    .invitationId(invitation.getId())
                    .groupPaiId(invitation.getGroupPaiId())
                    .groupName(groupInfo != null ? groupInfo.getName() : invitation.getGroupPaiId())
                    .groupAvatar(groupInfo != null ? groupInfo.getAvatar() : null)
                    .inviterAccount(invitation.getInviterAccount())
                    .inviterName(inviterInfo != null ? inviterInfo.getUserName() : invitation.getInviterAccount())
                    .inviterAvatar(inviterInfo != null ? inviterInfo.getPhoto() : null)
                    .inviteeAccount(invitation.getInviteeAccount())
                    .invitationCode(invitation.getInvitationCode())
                    .invitationMessage(invitation.getInvitationMessage())
                    .invitationStatus(invitation.getInvitationStatus())
                    .invitationStatusName(getInvitationStatusName(invitation.getInvitationStatus()))
                    .expireTime(invitation.getExpireTime())
                    .responseTime(invitation.getResponseTime())
                    .ext(json2map(invitation.getExt()))
                    .createDate(invitation.getCreateDate())
                    .updateDate(invitation.getUpdateDate())
                    .build();
        }).collect(Collectors.toList());
    }

    /**
     * 转换为响应VO
     */
    private GroupInvitationResponseVO convertToResponseVO(GroupInvitationEntity invitation) {
        GroupInfoEntity groupInfo = groupInfoDAO.findByPaiId(invitation.getGroupPaiId());
        List<UserBaseResponseInfoVO> inviterInfos = userService.batchGetUserListInfoFromCache(
                Collections.singletonList(invitation.getInviterAccount()));
        UserBaseResponseInfoVO inviterInfo = inviterInfos.isEmpty() ? null : inviterInfos.get(0);
        
        return GroupInvitationResponseVO.builder()
                .invitationId(invitation.getId())
                .groupPaiId(invitation.getGroupPaiId())
                .groupName(groupInfo != null ? groupInfo.getName() : invitation.getGroupPaiId())
                .groupAvatar(groupInfo != null ? groupInfo.getAvatar() : null)
                .inviterAccount(invitation.getInviterAccount())
                .inviterName(inviterInfo != null ? inviterInfo.getUserName() : invitation.getInviterAccount())
                .inviterAvatar(inviterInfo != null ? inviterInfo.getPhoto() : null)
                .inviteeAccount(invitation.getInviteeAccount())
                .invitationCode(invitation.getInvitationCode())
                .invitationMessage(invitation.getInvitationMessage())
                .invitationStatus(invitation.getInvitationStatus())
                .invitationStatusName(getInvitationStatusName(invitation.getInvitationStatus()))
                .expireTime(invitation.getExpireTime())
                .responseTime(invitation.getResponseTime())
                .ext(json2map(invitation.getExt()))
                .createDate(invitation.getCreateDate())
                .updateDate(invitation.getUpdateDate())
                .build();
    }

    /**
     * 获取邀请状态名称
     */
    private String getInvitationStatusName(Integer status) {
        GroupInvitationStatusEnum statusEnum = GroupInvitationStatusEnum.getByStatus(status);
        return statusEnum != null ? statusEnum.getStatusName() : "未知";
    }

    /**
     * 将 JSON 字符串解析为 Map 对象
     */
    @SuppressWarnings("unchecked")
    private Map<String, Object> json2map(String json) {
        return StringUtils.isBlank(json) ? null : JsonUtil.fromJson(json, Map.class);
    }
}
